package org.primefaces.model.chart.flow;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.primefaces.json.JSONException;
import org.primefaces.json.JSONObject;
import org.primefaces.util.ArrayUtils;
import org.primefaces.util.HTML;

public abstract class AbstractFlowGraph {

	private final static Logger logger = Logger
			.getLogger(AbstractFlowGraph.class.getName());

	public static final String ID = "id";
	public static final String STATE = "state";
	public static final String ON_CLICK = "onClick";
	public static final String ON_CONTEXT_MENU = "onContextMenu";
	public static final String ON_DBLCLICK = "onDblClick";
	public static final String ON_MOVE = "onMove";
	public static final String ON_ROPE = "onRope";

	// 画图的方法
	public static final String CREATE_FUNCTION = "createFunction";

	public static final String[] FLOW_EVENTS = ArrayUtils.concat(
			HTML.COMMON_EVENTS, new String[] { ON_CLICK, ON_CONTEXT_MENU,
					ON_DBLCLICK, ON_MOVE, ON_ROPE, CREATE_FUNCTION });

	public static final String EXTEND_DATA = "extendData";

	/**
	 * ID
	 */
	private String id;

	/**
	 * 状态类型
	 */
	private FlowGraphStateType state;

	/**
	 * 属性
	 */
	private Map<String, String> attributes;

	/**
	 * 扩展的数据
	 */
	private Map<String, String> extendData;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public FlowGraphStateType getState() {
		return state;
	}

	public void setState(FlowGraphStateType state) {
		this.state = state;
	}

	public Map<String, String> getAttributes() {
		return attributes;
	}

	public String getAttribute(String key) {
		if (this.attributes != null && key != null) {
			return this.attributes.get(key);
		}
		return null;
	}

	public boolean hasAttribute(String key) {
		if (this.attributes != null && key != null) {
			return this.attributes.containsKey(key);
		}
		return false;
	}

	public void setAttributes(Map<String, String> attributes) {
		this.attributes = attributes;
	}

	public void addAttribute(String key, String value) {
		if (this.attributes == null) {
			this.attributes = new HashMap<String, String>();
		}
		this.attributes.put(key, value);
	}

	public Map<String, String> getExtendData() {
		return extendData;
	}

	public void setExtendData(Map<String, String> extendData) {
		this.extendData = extendData;
	}

	public void addExtendData(String key, String value) {
		if (this.extendData == null) {
			this.extendData = new HashMap<String, String>();
		}
		this.extendData.put(key, value);
	}

	public void setExtendData(JSONObject jo) {
		try {
			if (jo != null) {
				Map<String, String> rtn = new HashMap<String, String>();
				String key, value;
				for (Iterator<?> iter = jo.keys(); iter.hasNext();) {
					key = (String) iter.next();
					value = jo.get(key).toString();
					rtn.put(key, value);
				}
				this.extendData = rtn;
			}
		} catch (JSONException e) {
			logger.log(Level.SEVERE, "Error in transfer from json object.");
		}
	}

	public JSONObject toJSON() {
		try {
			JSONObject jo = new JSONObject();
			if (this.id != null)
				jo.put(ID, this.id);

			if (this.state != null)
				jo.put(STATE, this.state.getName());

			if (this.attributes != null) {
				for (String e : FLOW_EVENTS) {
					if (this.hasAttribute(e)) {
						jo.put(e, this.attributes.get(e));
					}
				}
			}

			jo.put(CREATE_FUNCTION, this.getCreateFunction());

			if (this.extendData != null) {
				String key, value;
				JSONObject ed = new JSONObject();
				for (Iterator<String> iter = this.extendData.keySet()
						.iterator(); iter.hasNext();) {
					key = iter.next();
					value = this.extendData.get(key);
					ed.put(key, value);
				}
				jo.put(EXTEND_DATA, ed);
			}
			return jo;
		} catch (JSONException e) {
			logger.log(Level.SEVERE, "Error in transfer to json object.");
		}
		return null;
	}

	public void clear() {
		this.id = null;
		this.state = null;
		this.attributes = null;
		this.extendData = null;
	}

	public void construct(JSONObject json) {
		try {
			if (json.has(ID))
				this.id = json.getString(ID);

			if (json.has(STATE))
				this.state = FlowGraphStateType.get(json.getString(STATE));

			for (String e : FLOW_EVENTS) {
				if (json.has(e))
					addAttribute(e, json.getString(e));
			}

			if (json.has(EXTEND_DATA))
				this.setExtendData(json.getJSONObject(EXTEND_DATA));
		} catch (JSONException e) {
			logger.log(Level.SEVERE, "Error in transfer from json object.");
		}
	}

	public String getCreateFunction() {
		return this.getAttribute(CREATE_FUNCTION);
	}

}
